package com.boss.salary.service.impl;

import com.boss.common.entity.PageDTO;
import com.boss.common.entity.WfActionDTO;
import com.boss.common.enums.StatusCodeEnum;
import com.boss.common.service.ICommonService;
import com.boss.common.util.DateUtils;
import com.boss.framework.dto.PaginationDTO;
import com.boss.framework.exception.AppRuntimeException;
import com.boss.salary.constant.SystemDictConstant;
import com.boss.salary.dao.*;
import com.boss.salary.entity.*;
import com.boss.salary.service.IFormulaManageService;
import com.boss.salary.service.IRedisService;
import com.boss.salary.service.ISalaryHistoryAsyncService;
import com.boss.salary.service.ISalaryHistoryService;
import com.boss.salary.vo.SalaryColumnWithStateVO;
import com.boss.salary.vo.SalaryMonthEndVO;
import com.boss.salary.workflow.service.ISalaryWorkFlowService;
import com.boss.sys.ca.user.dto.UserDTO;
import com.boss.sys.utils.SysUtils;
import com.singularsys.jep.JepException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

@Service
@EnableAsync
public class SalaryHistoryServiceImpl implements ISalaryHistoryService {
    /**
     * 引入日志框架常量
     */
    private static final Logger logger = LoggerFactory.getLogger(SalaryHistoryServiceImpl.class);
    private static final String COLUMN_PREFIX = "getS";

    private static DateFormat df = new SimpleDateFormat("yyyy-MM");

    private Class<? extends Object> clazz = null;
    private Method[] methods = null;

    /**
     * 应发工资
     **/
    private final String YF = "3C4B5B347C9F420BB8D4B86572A5F178";
    /**
     * 实发工资
     **/
    private final String SF = "46F1370C5F2A4D31AD196718A93DC470";

    @Autowired
    private ISalaryWorkFlowService iSalaryWorkFlowService;
    @Autowired
    private IFormulaManageService formulaManageService;
    @Autowired
    private ICommonService commonService;

    @Autowired
    private ISalaryHistoryDao iSalaryHistoryDao;
    @Autowired
    private ISalaryMonthEndDao iSalaryMonthEndDao;
    @Autowired
    private IAgencyVerifyDao iAgencyVerifyDao;
    @Autowired
    private IAgencyInfoDao iAgencyInfoDao;
    @Autowired
    private IPersonInfoDao iPersonInfoDao;
    @Autowired
    private IAgencySalaryDao iAgencySalaryDao;
    @Autowired
    private IAgencySalaryHistoryDao agencySalaryHistoryDao;
    @Autowired
    private ISalaryBasedataDao salaryBasedataDao;
    @Autowired
    private ISalaryMonthBeginDao salaryMonthBeginDao;
    @Autowired
    private ISalaryMonthEndSubmitDao salaryMonthEndSubmitDao;
    @Autowired
    private IPersonExtSubmitDao personExtSubmitDao;
    @Autowired
    private IPersonExtBeginDao personExtBeginDao;
    @Autowired
    private IPersonExtDao personExtDao;
    @Autowired
    private IPaymentBackHistoryDao paymentBackHistoryDao;
    @Autowired
    private IPersonOperateDao personOperateDao;
    @Autowired
    private IRedisService redisService;
    @Autowired
    private ISalaryHistoryAsyncService SalaryHistoryAsyncService;

    @Override
    public Map<String,String> saveMonthEnd(Integer year, String province, List<AgencyVerify> agencyVerifyLists) throws InvocationTargetException, IllegalAccessException, ParseException, NoSuchMethodException, JepException {
        logger.info("----------------月结Begin---------------------");
        // 1-12月份的单位id集合
        List<String> agencyIds = new ArrayList<>();
        // 1-12月份外的单位id集合
        List<String> welfareAgencyIds = new ArrayList<>();
        // 获取单位审核表中当前月份
        List<String> monthEndAgencyIds = new ArrayList<>();
        Map<String,String> requestMap=new HashMap<>();
        for(AgencyVerify agencyVerify:agencyVerifyLists){
            monthEndAgencyIds.add(agencyVerify.getAgencyId());
        }
        List<AgencyVerify> agencyVerifyList = iAgencyVerifyDao.getAgencyVerifyByAgencyIds(monthEndAgencyIds);
        if (agencyVerifyList.size() > 0) {
            // 1-12 月份每个单位对应的月份集合
            Map<String, String> monthMap = new HashMap<>(agencyVerifyList.size());
            Map<String, String> agencyNameMap = new HashMap<>(agencyVerifyList.size());
            Map<String, String> agencyCodeMap = new HashMap<>(agencyVerifyList.size());
            // 1-12 月份外每个单位对应的月份集合
            Map<String, String> welfareMonthMap = new HashMap<>(agencyVerifyList.size());
            //    批量修改自动上报但单位端存在修改的数据表参数集合
            List<Object[]> personOperateUpdateList = new ArrayList<>();
            // 根据单位审核状态表，获取每个单位当前未月结的月份
            for (AgencyVerify agencyVerify : agencyVerifyList) {
                String salaryMonth = agencyVerify.getSalaryMonth();
                String agencyId = agencyVerify.getAgencyId();
                if (Integer.parseInt(salaryMonth.split("-")[1]) > 12) {
                    welfareMonthMap.put(agencyVerify.getAgencyId(), salaryMonth);
                    welfareAgencyIds.add(agencyId);
                } else {
                    agencyIds.add(agencyId);
                    monthMap.put(agencyId, salaryMonth);//单位月份
                    agencyNameMap.put(agencyId,agencyVerify.getAgencyName());//单位名称
                    agencyCodeMap.put(agencyId,agencyVerify.getAgencyCode());//单位编码
                  if(SystemDictConstant.ENABLE.equals(agencyVerify.getIsAuto())) {//自动上报单位需要处理上月编报数据
                      // 获取下个月
                      Date date = df.parse(salaryMonth);
                      ZoneId zoneId = ZoneId.systemDefault();
                      LocalDateTime localDateTime = LocalDateTime.ofInstant(date.toInstant(), zoneId);
                      String nextMonth = localDateTime.plusMonths(1).format(DateTimeFormatter.ofPattern("yyyy-MM"));
                      Object[] updateObjects = new Object[]{
                              nextMonth, agencyId,salaryMonth
                      };
                      personOperateUpdateList.add(updateObjects);
                  }
                }
            }
//
            AgencyVerify agencyVerify1=new AgencyVerify();
            for(AgencyVerify agencyVerify:agencyVerifyList) {
                if (null != agencyVerify.getSalaryMonth() && !"null".equals(agencyVerify.getSalaryMonth())) {
                    agencyVerify1.setSalaryMonth(agencyVerify.getSalaryMonth());
                    break;
                }
            }
           // String uuid=agencyVerify1.getSalaryMonth()+"-"+province+"lunarKnot";
            String uuid="2021-"+province+"-lunarKnot";
            logger.info("月结进度:"+uuid);
            redisService.put(uuid, 0);
            requestMap.put("guid",uuid);
          //
            // 1-12月份月结
            if (agencyIds.size() > 0) {
                SalaryHistoryAsyncService.saveMonthEndAsynchronous(year,province,agencyIds,monthMap,agencyNameMap,agencyCodeMap,personOperateUpdateList,uuid);
                // 1-12月份外的月结
                if (welfareAgencyIds.size() > 0) {
                    // TODO
                }
                }
            logger.info("----------------月结End---------------------");



        }

        return  requestMap;
    }

    /**
     * 缓解月结数据库超时问题通过循环分成小的事务
     * @throws ParseException
     * @throws InvocationTargetException
     * @throws IllegalAccessException
     * @throws NoSuchMethodException
     * @throws JepException
     */
//    @Async
//    @Override
//    public  void saveMonthEndAsynchronous(Integer year, String province, List<String> agencyIds, Map<String, String> monthMap, Map<String, String> agencyNameMap, Map<String, String> agencyCodeMap, List<Object[]> personOperateUpdateList, String uuid) throws ParseException, InvocationTargetException, IllegalAccessException, NoSuchMethodException, JepException {
//        StringBuffer requestMessage=new StringBuffer();
//        DecimalFormat df=new DecimalFormat("0.00");
//        logger.info("=======单位月结异步方法开始==============");
//        for(int i=0;i<agencyIds.size();i++){
//           saveMonthEnds(year,province,agencyIds.get(i),monthMap,agencyNameMap,agencyCodeMap,personOperateUpdateList,requestMessage);
//            redisService.put(uuid,df.format((float)(i+1)/agencyIds.size()));
//            System.out.println(df.format((float)(i+1)/agencyIds.size()));
//            if(i+1==agencyIds.size()){
//                redisService.del(province+"lunarKnot");
//            }
//        }
//        if(StringUtils.isEmpty(requestMessage.toString())) {
//            redisService.put(uuid, "S");
////            redisService.del(uuid);
//        }else{
//            redisService.put(uuid,requestMessage.toString());
////            redisService.del(uuid);
//        }
//        logger.info("=======单位月结异步方法结束==============");
//       }
//
//        @Override
//        @Transactional(rollbackFor = Exception.class)
//        public  void saveMonthEnds(Integer year, String province, String agencyId, Map<String, String> monthMap, Map<String, String> agencyNameMap, Map<String, String> agencyCodeMap, List<Object[]> personOperateUpdateList,StringBuffer requestMessage) throws ParseException, InvocationTargetException, IllegalAccessException, NoSuchMethodException, JepException {
//
//        try{
//            Thread.currentThread().sleep(1000);
//            // 批量修改单位审核表的上报状态后，增加下个月的初始数据
//            logger.info("==================批量修改审核表数据 Begin ================");
//            batchAgencyVerify(year, province,agencyId, monthMap,agencyNameMap,agencyCodeMap);
//            logger.info("==================批量修改审核表数据 End ================");
//
//            logger.info("==================批量存储单位历史表数据 Begin ================");
//            // 将单位信息存储到历史表
//            batchSaveAgencyHistory(province,agencyId, monthMap);
//            logger.info("==================批量存储单位历史表数据 End ================");
//            logger.info("==================批量存储人员历史表数据 Begin ================");
//            // 将人员信息存储到历史表
//            batchSavePersonHistory(province,agencyId, monthMap);
//            logger.info("==================批量存储人员历史表数据 End ================");
//            logger.info("==================批量存储工资表历史表数据 Begin ================");
//            // 转换工资表数据并添加到历史表
//            batchSaveSalaryHistory(province,agencyId, monthMap);
//            logger.info("==================批量存储工资表历史表数据 End ================");
//            logger.info("==================批量存储工资表月初表数据 Begin ================");
//            // 转换工资表数据并添加到历史表
//            batchSaveSalaryMonthBegin(province, agencyId);
//            logger.info("==================批量存储工资表月初表数据 End ================");
//            logger.info("==================批量存储支付回盘数据 Begin ================");
//            //支付回盘信息保存到历史表中，同时清空回盘信息
//            batchPaymentBack(agencyId,monthMap);
//            logger.info("==================批量存储支付回盘数据 End ================");
//            logger.info("==================批量存储银行回盘数据 Begin ================");
//            //银行回盘信息保存到历史表中，同时清空回盘信息
//            batchBankBack(agencyId,monthMap);
//            logger.info("==================批量存储银行回盘数据 End ================");
//            //若自动上报单位不为空则修改上月编报的数据为本月
//            if(!CollectionUtils.isEmpty(personOperateUpdateList)){
//                //将personOperateUpdateList才分 如果id相等走方法
//                for(Object[] personOperate:personOperateUpdateList){
//                    for(int i=0;i<personOperate.length;i++ ){
//                        if(personOperate[i].equals(agencyId)){
//                            // 批量修改自动上报单位上月修改数据状态改为下个月
//                            logger.info("==================批量修改自动上报单位上月修改数据状态改为下个月 Begin ================");
//                            personOperateDao.batchUpdateAutoMonthEnd(personOperateUpdateList);
//                            logger.info("==================批量修改自动上报单位上月修改数据状态改为下个月 End ================");
//                            logger.info("==================批量修改自动上报单位上月附件数据状态改为下个月 Begin ================");
//                            personOperateDao.batchUpdateAutoFile(personOperateUpdateList);
//                            logger.info("==================批量修改自动上报单位上月附件数据状态改为下个月 End ================");
//                        }
//                    }
//                }
//            }
//            }catch (Exception e){
//                logger.info("月结后续方法错误：",e);
//                 requestMessage.append("F"+e.getMessage());
//                }
//
//    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> checkRevokeMonthEnd(List<String> agencyIds, String salaryMonth) {
        Map<String, Object> result = new HashMap<>(2);
        boolean flag = true;
        String message = "";
        List<AgencyVerify> list = iAgencyVerifyDao.getAgencyVerifyByAgencyIds(agencyIds);
        if (!StringUtils.isEmpty(list) && list.size() > 0) {
            Set<Integer> set = list.stream().map(AgencyVerify::getIsSubmitInAgency).collect(Collectors.toSet());
            if (set.size() == 2) {
                flag = false;
                message = "存在当月已送审的单位，不允许撤销月结！";
                result.put("flag", flag);
                result.put("message", message);
                return result;
            } else if (set.size() == 1) {
                List<Integer> setList = new ArrayList<>(set);

            }
            String currentMonth = list.get(0).getSalaryMonth() + "-01";
            String month = LocalDate.parse(salaryMonth + "-01", DateTimeFormatter.ofPattern("yyyy-MM-dd")).plusMonths(1).toString();
            if (!currentMonth.equals(month)) {
                flag = false;
                message = "只允许反月结当前月数据！";
                result.put("flag", flag);
                result.put("message", message);
                return result;
            }
        }
        result.put("flag", flag);
        result.put("message", message);
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void revokeMonthEnd(SalaryMonthEnd salaryMonthEnd) {
        List<SalaryMonthEndVO> salaryMonthEnds= iSalaryHistoryDao.getSalaryMonthHistory(salaryMonthEnd.getMonth(), salaryMonthEnd.getAgencyIds());
//        List<SalaryMonthEndVO> querySalaryMonthEnd= iSalaryHistoryDao.querySalaryMonthHistory(salaryMonthEnd.getMonth(), salaryMonthEnd.getAgencyIds());
        List<PersonExt> personExts=iPersonInfoDao.getPersonExtByHistory(salaryMonthEnd.getMonth(), salaryMonthEnd.getAgencyIds());
        List<SalaryPaymentRequisitionBack> spList=paymentBackHistoryDao.getPaymentHisDatas(salaryMonthEnd.getMonth(), salaryMonthEnd.getAgencyIds());
        List<SalaryBankPayBack> sbpList=paymentBackHistoryDao.getBankBackDatas(salaryMonthEnd.getAgencyIds());
        try {
//            iSalaryMonthEndDao.batchSaveSalaryMonthEnd(querySalaryMonthEnd);
            salaryMonthEndSubmitDao.batchSaveSalaryMonthSubmit(salaryMonthEnds);
            personExtSubmitDao.batchSavePersonExtSubmit(personExts);
        } catch (Exception e) {
            logger.info(" ==== 反月结回填上报数据异常 ====");
            e.printStackTrace();
        }
        logger.info(" ==== 删除单位信息历史表 ====");
        iAgencyInfoDao.deleteAgencyHistory(salaryMonthEnd.getMonth(), salaryMonthEnd.getAgencyIds());
        logger.info(" ==== 删除人员信息历史表 ====");
        iPersonInfoDao.deletePersonHistory(salaryMonthEnd.getMonth(), salaryMonthEnd.getAgencyIds());
        logger.info(" ==== 删除单位工资项目挂接历史表 ====");
        iAgencySalaryDao.deleteAgencySalaryHistory(salaryMonthEnd.getMonth(), salaryMonthEnd.getAgencyIds());
        logger.info(" ==== 删除工资历史历史表 ====");
        iSalaryHistoryDao.deleteSalaryHistory(salaryMonthEnd.getMonth(), salaryMonthEnd.getAgencyIds());
        logger.info(" ==== 删除单位审核表已月结的数据 ====");
        iAgencyVerifyDao.deleteNoMonthEnd(salaryMonthEnd.getAgencyIds());
        logger.info(" ==== 修改指定月份的月结状态 ====");
        iAgencyVerifyDao.updateAlreadyMonthEnd(salaryMonthEnd.getMonth(), salaryMonthEnd.getAgencyIds());
        logger.info(" ==== 回填支付回单数据 ====");
        paymentBackHistoryDao.deletePaymentHistory(salaryMonthEnd.getMonth(), salaryMonthEnd.getAgencyIds());
        paymentBackHistoryDao.batchInsertPaymentDatas(spList);

        logger.info(" ==== 回填银行回盘数据 ====");
            paymentBackHistoryDao.deleteBankBackDatas(salaryMonthEnd.getAgencyIds());
            paymentBackHistoryDao.batchInsertBankBackHistoryDatas(sbpList);
    }

    /**
     * 根据单位id批量修改单位审核状态表中的是否月结后
     * 批量增加下个月的初始数据
     *
     * @param agencyId
     * @param monthMap
     */
    void batchAgencyVerify(Integer year, String province, String agencyId, Map<String, String> monthMap, Map<String, String> nameMap, Map<String, String> codeMap) throws ParseException {

        String currentTime = String.valueOf(DateUtils.getCurrentTimeStamp());
        //    批量更新单位审核表上报状态集合
        List<Object[]> agencyVerifyUpdatelist = new ArrayList<>();
        //    批量插入单位审核表参数集合
        List<Object[]> agencyVerifyInsertlist = new ArrayList<>();

        // 获取批量更新和批量插入的参数
//        for (String agencyId : agencyIds) {
            // 当前月
            String currentMonth = monthMap.get(agencyId);
            String agencyName = nameMap.get(agencyId);
            String agencyCode = codeMap.get(agencyId);
            // 获取下个月
            Date date = df.parse(currentMonth);
            ZoneId zoneId = ZoneId.systemDefault();
            LocalDateTime localDateTime = LocalDateTime.ofInstant(date.toInstant(), zoneId);
            String nextMonth = localDateTime.plusMonths(1).format(DateTimeFormatter.ofPattern("yyyy-MM"));
            String nextYear = localDateTime.plusMonths(1).format(DateTimeFormatter.ofPattern("yyyy"));

            // 批量更新参数集合
            Object[] updateObjects = new Object[]{
                    SystemDictConstant.IS_TRUE, currentTime, agencyId, currentMonth
            };
            agencyVerifyUpdatelist.add(updateObjects);
            // 批量插入参数集合
            Object[] insertObjects = new Object[]{
                    SysUtils.generateGuid(), SysUtils.generateGuid(), currentTime, currentTime, agencyId, nextMonth,
                    SystemDictConstant.NO_SUBMIT,
                    SystemDictConstant.NO_SUBMIT, SystemDictConstant.NO_SUBMIT, SystemDictConstant.NO_SUBMIT,
                    SystemDictConstant.IS_FALSE, SystemDictConstant.IS_FALSE, SystemDictConstant.IS_FALSE,
                    SystemDictConstant.IS_FALSE, SystemDictConstant.IS_FALSE, SystemDictConstant.IS_FALSE,
                    SystemDictConstant.IS_FALSE, "", "", SystemDictConstant.IS_FALSE, 0, 0, 0, 0, 0, SystemDictConstant.IS_FALSE,
                    province, nextYear,0,agencyName,agencyCode
            };
            agencyVerifyInsertlist.add(insertObjects);
//        }


        // 批量更新单位审核表月结状态
        iAgencyVerifyDao.batchUpdateMonthEnd(agencyVerifyUpdatelist);
        // 批量增加单位审核表下个月的初始数据
        iAgencyVerifyDao.batchInsertInitDate(agencyVerifyInsertlist);
    }


    /**
     * 批量插入单位信息到历史表
     *
     * @param agencyId
     * @param monthMap
     */
    void batchSaveAgencyHistory(String province, String agencyId, Map<String, String> monthMap) {
        // 根据id获取单位信息
      AgencyInfo agencyInfo = iAgencyInfoDao.selectFirstAuthAgencyData(agencyId);
//        if (agencyInfoList.size() > 0) {
            String currentTime = String.valueOf(DateUtils.getCurrentTimeStamp());
            List<Object[]> saveList = new ArrayList<>();
//            for (AgencyInfo agencyInfo : agencyInfoList) {
                Object[] objects = new Object[]{
                        SysUtils.generateGuid(), agencyInfo.getId(), agencyInfo.getBizKey(), currentTime, currentTime,
                        monthMap.get(agencyInfo.getId()), agencyInfo.getId(), agencyInfo.getAgencyAddress(), agencyInfo.getZip(),
                        agencyInfo.getAgencyAdmLevelCode(), agencyInfo.getAdmDepTypeCode(), agencyInfo.getAgencyBankName(),
                        agencyInfo.getAgencyBankCardno(), agencyInfo.getCentralAgencyCode(), agencyInfo.getAgencyLeader(),
                        agencyInfo.getIsUniSala(), agencyInfo.getRemarks(), agencyInfo.getHasFile(), agencyInfo.getFundSupCode(),
                        agencyInfo.getCapitalType(), agencyInfo.getVerifyState(), agencyInfo.getEffectiveYear(),
                        agencyInfo.getIsDeleted(),province,agencyInfo.getAgencyName(),agencyInfo.getAgencyCode(),agencyInfo.getParentId()
                };
                saveList.add(objects);
//            }
            // 批量插入到历史表
            iAgencyInfoDao.batchSaveAgencyHistory(saveList);
//        }
    }

    /**
     * 批量插入人员信息到历史表
     *
     * @param agencyId
     * @param monthMap
     */
    void batchSavePersonHistory(String province, String agencyId, Map<String, String> monthMap) {
        // 根据单位id获取用户信息
        List<PersonInfo> personInfoList = iPersonInfoDao.getPersonInfoByAgencyIds(agencyId);
//        if (personInfoList.size() > 0) {
            String currentTime = String.valueOf(DateUtils.getCurrentTimeStamp());
            List<Object[]> saveList = new ArrayList<>();
            for (PersonInfo personInfo : personInfoList) {
                Object[] objects = new Object[]{
                        SysUtils.generateGuid(), personInfo.getId(), monthMap.get(personInfo.getAgencyId()), currentTime, currentTime,
                        personInfo.getId(), personInfo.getPersonAddress(), personInfo.getAgencyId(), personInfo.getDeptId(),
                        personInfo.getAgencyCode(), personInfo.getEnterAgencyDate(), personInfo.getRetireDate(),
                        personInfo.getPersonTypeCode(), personInfo.getPersonIdeCode(), personInfo.getEndDate(),
                        personInfo.getDeadDate(), personInfo.getRemarks(), personInfo.getSalaCardNo(), personInfo.getSalaCardBank(),
                        personInfo.getGovCredCardNo(), personInfo.getGovCredCardBank(), personInfo.getStartDate(),
                        personInfo.getMeritPayCode(), personInfo.getSchRecCode(), personInfo.getPosCode(), personInfo.getGrCode(),
                        personInfo.getTecGrCode(), personInfo.getIsAuth(), personInfo.getSalaGrCode(), personInfo.getPersonState(),
                        personInfo.getChangeState(), personInfo.getPerSourceCode(), personInfo.getIsSpecialPost(),
                        personInfo.getIsInsurance(), personInfo.getIsUniSala(), personInfo.getIsStopSalary(), personInfo.getIsDeleted(),province,
                        personInfo.getPersonTypeId(), personInfo.getPostId(), personInfo.getGradeId(), personInfo.getLevelId(),personInfo.getPersonName(),
                        personInfo.getIdenNo(),personInfo.getState(),personInfo.getShowOrder(),personInfo.getPhone(),personInfo.getPersonnelCode(),
                        personInfo.getFuncCode(),personInfo.getFuncName(),personInfo.getFuncCode()
                };
                saveList.add(objects);
            }
            // 批量插入到历史表
            iPersonInfoDao.batchSavePersonHistory(saveList);
//       }
    }

    /**
     * 将单位工资挂接表数据存储到历史表
     *
     * @param agencyIds
     * @param monthMap
     */
    private void batchSaveAgencySalaryHistory(String province,List<String> agencyIds, Map<String, String> monthMap) {
        List<AgencySalary> agencySalaryList = iAgencySalaryDao.getInfoByAgencyIds(agencyIds);
        if (agencySalaryList.size() > 0) {
            String currentTime = String.valueOf(DateUtils.getCurrentTimeStamp());
            List<Object[]> saveList = new ArrayList<>(agencySalaryList.size());
            for (AgencySalary agencySalary : agencySalaryList) {
                Object[] objects = new Object[]{
                        SysUtils.generateGuid(), currentTime, currentTime, monthMap.get(agencySalary.getAgencyId()), agencySalary.getAgencyId(),
                        agencySalary.getSalaryId(), agencySalary.getIsAccsalwithhold(), agencySalary.getColumnName(),
                        agencySalary.getIsDeleted(),province
                };
                saveList.add(objects);
            }
            iAgencySalaryDao.batchSaveAgencySalaryHistory(saveList);
        }
    }

    /**
     * 转换工资表的数据，并批量存储到数据库历史表
     *
     * @param agencyIds
     * @param monthMap
     * @throws InvocationTargetException
     * @throws IllegalAccessException
     */
    void batchSaveSalaryHistory(String province, String agencyIds, Map<String, String> monthMap) throws InvocationTargetException, IllegalAccessException {
        // 获取当月表中对应单位的数据
        List<SalaryMonthEnd> salaryMonthEndList = iSalaryMonthEndDao.getSalaryMonthEndByAgencyIds(agencyIds);
        // 最终参数集合
        List<Object[]> lists = new ArrayList<>();
        // 将当月表的数据复制到历史表中
        for (SalaryMonthEnd salaryMonthEnd : salaryMonthEndList) {
            clazz = null;
            methods = null;
            // 转换工资表数据并添加到历史表
            List<Object> list = new ArrayList<>();
            // 历史表id
            list.add(SysUtils.generateGuid());
            // 历史表对应的工资表id
            list.add(salaryMonthEnd.getId());
            // 历史表创建时间
            list.add(String.valueOf(DateUtils.getCurrentTimeStamp()));
            // 历史表更新时间
            list.add(String.valueOf(DateUtils.getCurrentTimeStamp()));
            // 历史表月结时间
            list.add(monthMap.get(salaryMonthEnd.getAgencyId()));
            // 历史表单位id
            list.add(salaryMonthEnd.getAgencyId());
            // 历史表人员id
            list.add(salaryMonthEnd.getPersonId());
            // 是否十三月工资
            list.add(salaryMonthEnd.getIsThirteen());
            //区划
            list.add(province);
            // 历史表 s1~s100
            for (int i = 1; i < 101; i++) {
                list.add(converBeanFiledForObject(salaryMonthEnd, COLUMN_PREFIX + i));
            }
            // 将数据存储到最终要保存的数组中
            lists.add(list.toArray());
        }

        // 将数据批量插入到历史表
        iSalaryHistoryDao.batchSaveSalaryHistory(lists);
    }

    /**
     * 月结清零并计算，批量保存到月初表中
     * @param province
     * @param agencyId
     */
    void batchSaveSalaryMonthBegin(String province, String agencyId) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, JepException {
//        查询需要清零的工资项
        List<String> clearSalaryLIst = salaryBasedataDao.selectClearColumn(province);
//      查询需要操作的人员工资
//        List<SalaryMonthEndVO> salaryMonthEndSubmitVOList= new ArrayList<>();
//        List<SalaryMonthEndVO>  salaryMonthEndVOList=new ArrayList<>();
        List<String> agencyIds= new ArrayList<>();
        agencyIds.add(agencyId);
        //       / List<SalaryMonthEndVO salaryMonthEndSubmitVOList = iSalaryMonthEndDao.selectSalaryMonthEndSubmitWithSalaryType(province, agencyIds);
        List<SalaryMonthEndVO> salaryMonthEndSubmitVOList = iSalaryMonthEndDao.selectSalaryMonthEndSubmitWithSalaryTypes(province, agencyId);
//        List<SalaryMonthEndVO> salaryMonthEndVOList = iSalaryMonthEndDao.selectSalaryMonthEndWithSalaryType(province, agencyIds);
        List<SalaryMonthEndVO> salaryMonthEndVOList = iSalaryMonthEndDao.selectSalaryMonthEndWithSalaryTypes(province, agencyId);
//        如果没有需要清零的工资项，则直接保存到月初表中
        if(!CollectionUtils.isEmpty(clearSalaryLIst)){
            Class<?> salaryMonthEndVOClass = SalaryMonthEndVO.class;
//            将清零项都设置为0
            for(SalaryMonthEndVO salaryMonthEndSubmitVO : salaryMonthEndSubmitVOList){
                for(String column : clearSalaryLIst){
                    Method setMethod = salaryMonthEndVOClass.getDeclaredMethod("set" + column.substring(0,1).toUpperCase() + column.substring(1), Double.class);
                    setMethod.invoke(salaryMonthEndSubmitVO, Double.parseDouble("0"));
                }
           }

            salaryMonthEndSubmitVOList = formulaManageService.calculateByFormula(province, agencyIds, salaryMonthEndSubmitVOList);
            //        单位端数据如果没有需要清零的工资项，则直接保存到月初表中 将清零项都设置为0
            for(SalaryMonthEndVO salaryMonthEndVO : salaryMonthEndVOList){
                for(String column : clearSalaryLIst){
                    Method setMethod = salaryMonthEndVOClass.getDeclaredMethod("set" + column.substring(0,1).toUpperCase() + column.substring(1), Double.class);
                    setMethod.invoke(salaryMonthEndVO, Double.parseDouble("0"));
                }
            }

            salaryMonthEndVOList = formulaManageService.calculateByFormula(province, agencyIds, salaryMonthEndVOList);
        }



        // 保存修改后工资
        iSalaryMonthEndDao.batchUpdateSalaryMonthEnd(salaryMonthEndVOList);
//        将之前这些机构的月初工资数据清除
        salaryMonthBeginDao.batchPhysicalDeleteSalaryMonthBegin(province, agencyIds);
        salaryMonthBeginDao.batchSaveSalaryMonthBegin(salaryMonthEndSubmitVOList);
        personExtBeginDao.batchPhysicalDeletePersonExtBegin(province, agencyIds);
        List<PersonExt> personExts=personExtDao.queryPersonExtSubmit(agencyIds);
        personExtBeginDao.batchSavePersonExtBegin(personExts);
        //月结时清空该单位上报数据
        salaryMonthEndSubmitDao.batchPhysicalDeleteSalaryMonthSubmit(province, agencyIds);
        personExtSubmitDao.batchPhysicalDeletePersonExtSubmit(province, agencyIds);
    }

    /**
     * 月结批量处理支付回盘数据
     * @param agencyIds
     * @param monthMap
     */
    void batchPaymentBack(String agencyIds, Map<String, String> monthMap) {
        List<SalaryPaymentRequisitionBack> spList=paymentBackHistoryDao.getPayBackData(agencyIds);
        paymentBackHistoryDao.deletePayBackData(agencyIds);
        paymentBackHistoryDao.batchInsertPayBackHistoryData(spList,monthMap);

    }
//    private void batchPaymentBack(String agencyIds,Map<String, String> monthMap) {
//
//    }

    /**
     * 月结批量处理银行回盘数据
     * @param agencyIds
     * @param monthMap
     */
    void batchBankBack(String agencyIds, Map<String, String> monthMap) {

        List<SalaryBankPayBack> spList=paymentBackHistoryDao.getBankBackData(agencyIds);
        paymentBackHistoryDao.deleteBankBackData(agencyIds);
        paymentBackHistoryDao.batchInsertBankBackHistoryData(spList,monthMap);
    }
    /**
     * 通过反射类，获取字段值
     *
     * @param bean
     * @param column
     * @param <T>
     * @return
     */
    private <T> Object converBeanFiledForObject(T bean, String column) throws InvocationTargetException, IllegalAccessException {
        Object object = null;
        if (clazz != null && methods != null) {
            for (Method method : methods) {
                if (column.equals(method.getName())) {
                    object = method.invoke(bean);
                    break;
                }
            }
        } else {
            clazz = bean.getClass();
            methods = clazz.getDeclaredMethods();
            if (methods.length > 0) {
                for (Method method : methods) {
                    if (column.equals(method.getName())) {
                        object = method.invoke(bean);
                        break;
                    }
                }
            }
        }
        return object;
    }

    @Override
    public PageDTO getSalary(UserDTO userDTO, PaginationDTO paginationDTO, Map<String, Object> queryParam,List<String> childrenId) throws AppRuntimeException {
        // 获取应发工资和实发工资字段名
//        String s3 = iSalaryHistoryDao.getSalaryName(YF);
//        String s4 = iSalaryHistoryDao.getSalaryName(SF);
        // 获取工作流数据
//        List<String> bizKeys = new ArrayList<>();
        String bizKeys = "";
        WfActionDTO wfActionDTO = new WfActionDTO();
        // 菜单id
        wfActionDTO.setMenuguid(queryParam.get("menuid").toString());
        wfActionDTO.setBizKeyName("biz_key");
        wfActionDTO.setYear(userDTO.getYear()+"");
        wfActionDTO.setProvince(userDTO.getProvince());
        // 未确定
        if ("0".equals(queryParam.get("flag"))) {
            wfActionDTO.setStatus(StatusCodeEnum.TODO_BESENDBACK.getCode());
//            bizKeys = iSalaryWorkFlowService.queryWorkflowInfo(userDTO, wfActionDTO);
            bizKeys =commonService.getWorkflowWheresql(wfActionDTO,"c");
        }
        // 已确认
        else if ("1".equals(queryParam.get("flag"))) {
            // 获取已办
            wfActionDTO.setStatus(StatusCodeEnum.FINISHED.getCode());
//            bizKeys = iSalaryWorkFlowService.queryWorkflowInfo(userDTO, wfActionDTO);
            bizKeys =commonService.getWorkflowWheresql(wfActionDTO,"c");
            // 获取曾经办数据
            //wfActionDTO.setStatus(StatusCodeEnum.ONCE_FINISHED.getCode());
            //List<String> onceBizKeys = iSalaryWorkFlowService.queryWorkflowInfo(userDTO,wfActionDTO);
            if (StringUtils.isEmpty(bizKeys)) {
//                bizKeys = new ArrayList<>();
                bizKeys = "";
            }
           /* if (!StringUtils.isEmpty(onceBizKeys) && onceBizKeys.size() > 0) {
                bizKeys.addAll(onceBizKeys);
            }*/
        }
//        SalaryRental combined = iAgencyVerifyDao.fiscalCombined(queryParam, bizKeys,childrenId);
//        //实发
        queryParam.put("s1", "s1");
        //应发
        queryParam.put("s2", "s2");
        List<SalaryRental> salary = iSalaryHistoryDao.getSalary(paginationDTO, queryParam, bizKeys,childrenId);
        Integer index = 1;
        if(null==salary){
            return null;
        }else{
            if (salary.size() > 0) {
                for (SalaryRental salaryRental : salary) {
                    salaryRental.setIndex(index.toString());
                    index++;
                }
//            combined.setIndex("合计");
//            salary.add(0, combined);
            }

            int total = iSalaryHistoryDao.getSalaryNum(queryParam, bizKeys,childrenId);
            PageDTO<SalaryRental> pageDTO = new PageDTO<>();
            pageDTO.setRows(salary);
            pageDTO.setTotal(total);
            return pageDTO;
        }

    }

    @Override
    public PageDTO<SalaryRental> getSalaryMonthEndPage(PaginationDTO paginationDTO, Map<String, Object> queryParam, List<String> childrenIds) {
        List<SalaryRental> salary = iSalaryHistoryDao.getSalaryMonthEndPage(paginationDTO, queryParam, childrenIds);
        int total = iSalaryHistoryDao.getSalaryMonthEndTotal(queryParam, childrenIds);
        PageDTO<SalaryRental> pageDTO = new PageDTO<>();
        pageDTO.setRows(salary);
        pageDTO.setTotal(total);
        return pageDTO;
    }

    @Override
    public PageDTO<SalaryRental> getSalaryMonthHistoryPage(PaginationDTO paginationDTO, Map<String, Object> queryParam, List<String> childrenIds) {
        List<SalaryRental> salary = iSalaryHistoryDao.getSalaryMonthHistoryPage(paginationDTO, queryParam, childrenIds);
        int total = iSalaryHistoryDao.getSalaryMonthHistoryTotal(queryParam, childrenIds);
        PageDTO<SalaryRental> pageDTO = new PageDTO<>();
        pageDTO.setRows(salary);
        pageDTO.setTotal(total);
        return pageDTO;
    }

    @Override
    public List<Map<String, Object>> getSalaryHistoryPage(String agencyId,
                                                          String salaryMonth,
                                                          List<String> salaryItem,
                                                          String mofDivCode) {
        List<SalaryColumnWithStateVO> columnList = agencySalaryHistoryDao.selectSalaryColumnWithStateVO(agencyId, salaryMonth, salaryItem,mofDivCode);
//      查询当前月份该机构绑定的工资项字段
        List<Map<String, Object>> page = iSalaryHistoryDao.selectSalaryHistoryPage(agencyId, salaryMonth, columnList,mofDivCode);
//        int total = 0;
        if (!CollectionUtils.isEmpty(page)) {
//            total = iSalaryHistoryDao.selectSalaryHistoryTotal(agencyId);
            Map<String, Object> sum = iSalaryHistoryDao.selectSalaryHistorySum(agencyId, salaryMonth, columnList,mofDivCode);
            sum.put("index", "合计");
            page.add(0, sum);
        }
//        PageDTO<Map<String, Object>> pageDTO = new PageDTO<>();
//        pageDTO.setRows(page);
//        pageDTO.setTotal(total);
        return page;
    }

    @Override
    public List<SalaryRental> getSalaryMonth(Map<String, Object> queryParam, List<String> childrenIds) {
        return iSalaryHistoryDao.getSalaryMonth(queryParam,childrenIds);
    }

    @Override
    public List<SalaryRental> getSalaryMonthHistory(Map<String, Object> queryParam, List<String> childrenIds) {
        return iSalaryHistoryDao.getSalaryMonthHistory(queryParam,childrenIds);
    }

}
